package com.idroid.fragments;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.Toast;

import com.idroid.R;
import com.idroid.activities.FragmentTabsActivity;
import com.idroid.activities.ParkingListActivity;
import com.idroid.database.DatabaseService;
import com.idroid.dialogs.AddressDialog;
import com.idroid.dialogs.FilterDialog;
import com.idroid.dialogs.ZipCodeDialog;
import com.idroid.domain.AreaType;
import com.idroid.domain.LocationTracker;
import com.idroid.domain.ParkingArea;
import com.idroid.domain.SearchType;
import com.idroid.domain.SerializableLocation;

public class SearchFragment extends Fragment {

	static final double ONE_METER_IN_MILES = 0.000621371192;
	CheckBox filterCheckBox = null;
	private boolean maxPriceFilterEnabled;
	private double maxPriceFilter;
	private boolean areaTypeFilterEnabled;
	private AreaType areaFilter;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {

		if (data != null && data.getExtras().getBoolean("showsearch")) {
			((FragmentTabsActivity) this.getActivity()).getTabHost()
					.setCurrentTabByTag("search");

		} else if (data == null) {
		} else {

			((FragmentTabsActivity) this.getActivity()).getFragmentMap()
					.get(MapFragment.class)
					.onActivityResult(requestCode, resultCode, data);

			((FragmentTabsActivity) this.getActivity()).getTabHost()
					.setCurrentTabByTag("map");
		}

	}

	public CheckBox getFilterCheckBox() {
		return filterCheckBox;

	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View v = inflater.inflate(R.layout.search_fragment, container, false);
		v.setBackgroundDrawable(getResources().getDrawable(
				android.R.drawable.gallery_thumb));

		Button byAddressButton = (Button) v.findViewById(R.id.byAddressButton);
		Button byZipCodeButton = (Button) v.findViewById(R.id.byZipCodeButton);
		Button nearMeButton = (Button) v.findViewById(R.id.nearMeButton);
		filterCheckBox = (CheckBox) v.findViewById(R.id.filterCheckbox);

		byAddressButton.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {

				AddressDialog dialogFragment = AddressDialog
						.newInstance(SearchFragment.this);
				dialogFragment.show(SearchFragment.this.getFragmentManager(),
						"addressdialog");

			}
		});

		byZipCodeButton.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {

				ZipCodeDialog dialogFragment = ZipCodeDialog
						.newInstance(SearchFragment.this);
				dialogFragment.show(SearchFragment.this.getFragmentManager(),
						"zipcodedialog");

			}
		});

		nearMeButton.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				startSearchNearTheUser();

			}
		});

		filterCheckBox
				.setOnCheckedChangeListener(new OnCheckedChangeListener() {

					public void onCheckedChanged(CompoundButton buttonView,
							boolean isChecked) {

						maxPriceFilterEnabled = false;
						areaTypeFilterEnabled = false;
						maxPriceFilter = 0.0;
						areaFilter = AreaType.NoInformation;

						if (isChecked) {
							FilterDialog dialogFragment = FilterDialog
									.newInstance(SearchFragment.this);
							dialogFragment.show(
									SearchFragment.this.getFragmentManager(),
									"filterdialog");
						}

					}
				});

		return v;
	}

	public void startSearchByAddress(String passedAddress,
			boolean fromUsersLocation) {


		if (!Geocoder.isPresent()) {
			Toast.makeText(
					SearchFragment.this.getActivity(),
					"The emulator you are in does not support GeoCoding.  Please install \"Google APIs\" through the Android SDK Manager and configure a \"Google APIS\" Virtual Device",
					Toast.LENGTH_LONG).show();
		}

		Geocoder geocoder = new Geocoder(this.getActivity());
		List<Address> list = null;
		try {
			list = geocoder.getFromLocationName(passedAddress, 1);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		if (list != null && list.size() > 0) {
			Toast.makeText(SearchFragment.this.getActivity(),
					"Search by Address: " + passedAddress, Toast.LENGTH_SHORT)
					.show();

			Address addr = list.get(0);

			ArrayList<ParkingArea> areas = DatabaseService.getInstance()
					.getParkingAreasByCitySate(
							SearchFragment.this.getActivity(),
							addr.getLocality(), addr.getAdminArea(),
							maxPriceFilterEnabled, maxPriceFilter,
							areaTypeFilterEnabled, areaFilter);

			SerializableLocation location = null;
			if (fromUsersLocation) {
				try {
					location = new SerializableLocation(LocationTracker
							.getInstance().getCurrentLocation());
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} else {
				location = new SerializableLocation();
				location.setLatitude(addr.getLatitude());
				location.setLongitude(addr.getLongitude());
			}

			Intent i = new Intent(this.getActivity(), ParkingListActivity.class);
			i.putExtra(
					"parkingAreas",
					findDistanceFromPointAndSortList(location.getLatitude(),
							location.getLongitude(), areas));

			i.putExtra("searchType", SearchType.ByAddress);

			i.putExtra("startingLoc", (Serializable) location);

			startActivityForResult(i, 1);
		} else {
			Toast.makeText(SearchFragment.this.getActivity(),
					"That address was not valid.", Toast.LENGTH_SHORT).show();
		}

	}

	public void startSearchByZipCode(String zipCode, boolean fromUsersLocation) {

		int convertedZipCode = 0;
		boolean isValid = false;
		try {
			convertedZipCode = Integer.parseInt(zipCode);
			isValid = true;
		} catch (Exception e) {
			isValid = false;
		}

		if (isValid) {
			Geocoder geocoder = new Geocoder(this.getActivity());
			if (!Geocoder.isPresent()) {
				Toast.makeText(
						SearchFragment.this.getActivity(),
						"The emulator you are in does not support GeoCoding.  Please install \"Google APIs\" through the Android SDK Manager and configure a \"Google APIS\" Virtual Device",
						Toast.LENGTH_LONG).show();
			}
			List<Address> list = null;
			try {
				list = geocoder.getFromLocationName(
						Integer.toString(convertedZipCode), 1);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			if (list != null && list.size() > 0) {
				Address addr = list.get(0);

				Toast.makeText(SearchFragment.this.getActivity(),
						"Search by Zip Code: " + zipCode, Toast.LENGTH_SHORT)
						.show();
				ArrayList<ParkingArea> areas = DatabaseService.getInstance()
						.getParkingAreasByZipCode(
								SearchFragment.this.getActivity(),
								convertedZipCode, maxPriceFilterEnabled,
								maxPriceFilter, areaTypeFilterEnabled,
								areaFilter);

				Intent i = new Intent(this.getActivity(),
						ParkingListActivity.class);
				SerializableLocation location = null;
				if (fromUsersLocation) {
					try {
						location = new SerializableLocation(LocationTracker
								.getInstance().getCurrentLocation());
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				} else {
					location = new SerializableLocation();
					location.setLatitude(addr.getLatitude());
					location.setLongitude(addr.getLongitude());
				}
				i.putExtra(
						"parkingAreas",
						findDistanceFromPointAndSortList(
								location.getLatitude(),
								location.getLongitude(), areas));

				i.putExtra("searchType", SearchType.ByZipCode);

				i.putExtra("startingLoc", (Serializable) location);

				startActivityForResult(i, 1);
			}
		} else {
			Toast.makeText(SearchFragment.this.getActivity(),
					"The Zip Code Entered is Not Valid", Toast.LENGTH_SHORT)
					.show();
		}
	}

	public void startSearchNearTheUser() {
		Location location = null;
		try {
			location = LocationTracker.getInstance().getCurrentLocation();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		if (!Geocoder.isPresent()) {
			Toast.makeText(
					SearchFragment.this.getActivity(),
					"The emulator you are in does not support GeoCoding.  Please install \"Google APIs\" through the Android SDK Manager and configure a \"Google APIS\" Virtual Device",
					Toast.LENGTH_LONG).show();
		}

		Geocoder geocoder = new Geocoder(this.getActivity());
		List<Address> list = null;
		try {
			list = geocoder.getFromLocation(location.getLatitude(),
					location.getLongitude(), 1);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		if (list != null && list.size() > 0) {
			Address address = list.get(0);
			Toast.makeText(
					SearchFragment.this.getActivity(),
					"Search Near the User. Current Zip Code is: "
							+ address.getPostalCode(), Toast.LENGTH_SHORT)
					.show();

			ArrayList<ParkingArea> areas = DatabaseService.getInstance()
					.getParkingAreasByCitySate(
							SearchFragment.this.getActivity(),
							address.getLocality(), address.getAdminArea(),
							maxPriceFilterEnabled, maxPriceFilter,
							areaTypeFilterEnabled, areaFilter);

			Intent i = new Intent(this.getActivity(), ParkingListActivity.class);
			i.putExtra(
					"parkingAreas",
					findDistanceFromPointAndSortList(location.getLatitude(),
							location.getLongitude(), areas));

			i.putExtra("searchType", SearchType.NearMe);
			SerializableLocation serializeableLocation = new SerializableLocation(
					location);
			i.putExtra("startingLoc", (Serializable) serializeableLocation);

			startActivityForResult(i, 1);

		} else {
			Toast.makeText(SearchFragment.this.getActivity(),
					"Get out of the water!", Toast.LENGTH_SHORT).show();
		}

	}

	private ArrayList<ParkingArea> findDistanceFromPointAndSortList(double lat,
			double lon, ArrayList<ParkingArea> areas) {

		Location userLocation = new Location("");
		userLocation.setLatitude(lat);
		userLocation.setLongitude(lon);

		for (ParkingArea area : areas) {
			if (area.getHasPosition()) {
				Location areaLocation = new Location("");
				areaLocation.setLatitude(area.getLatitude());
				areaLocation.setLongitude(area.getLongitude());

				float distanceInMeters = userLocation.distanceTo(areaLocation);

				area.setDistanceFromUserInMiles((float) (ONE_METER_IN_MILES * distanceInMeters));
			}
		}

		Collections.sort(areas, new Comparator<ParkingArea>() {

			public int compare(ParkingArea lhs, ParkingArea rhs) {
				if (lhs.getDistanceFromUserInMiles() < rhs
						.getDistanceFromUserInMiles()) {
					return -1;
				}
				if (lhs.getDistanceFromUserInMiles() > rhs
						.getDistanceFromUserInMiles()) {
					return 1;
				}
				return 0;
			}
		});

		return areas;

	}

	public void setMaxPriceFilter(boolean maxPriceFilterEnabled,
			double maxPriceFilter) {
		this.maxPriceFilterEnabled = maxPriceFilterEnabled;
		this.maxPriceFilter = maxPriceFilter;

	}

	public void setAreaTypeFilter(boolean areaTypeFilterEnabled,
			AreaType filteredAreas) {
		this.areaTypeFilterEnabled = areaTypeFilterEnabled;
		this.areaFilter = filteredAreas;

	}

}